from entity.player import Card, Player

ILLEGAL = -1  # 用于表示结算非法

class SettlementCalculator:
    def __init__(self):
        # 记录上一张出过的牌，用于匹配花色或点数
        self.last_card = None
        # 记录各牌种已使用次数
        self.usage_counts = {
            "酒": 0,
            "桃": 0,
            "闪电": 0,
            "杀": 0,
            "技能": 0
        }
    def clone(self):
        new_calc = SettlementCalculator()
        new_calc.last_card = self.last_card  # 如果 Card 对象需要深拷贝，则可使用 copy.deepcopy(self.last_card)
        new_calc.usage_counts = self.usage_counts.copy()
        return new_calc

    def get_max_usage(self, card_name, player):
        """
        根据牌名和玩家装备情况返回该牌正常使用的最大次数
        """
        if card_name in ["酒", "桃", "闪电"]:
            return 1
        elif card_name == "杀":
            # 若装备了诸葛连弩，则视为无限制（这里用100次表示）
            if player.weapon is not None and player.weapon.name == "诸葛连弩":
                return 100
            else:
                return 2
        elif card_name == "技能":
            return 1
        else:
            # 其他牌默认无限制
            return float('inf')
    
    def settle(self, card, player):
        """
        结算一张卡牌。
        输入：Card对象（当前牌）以及玩家对象
        返回：结算后的分数；若非法则返回ILLEGAL（-1）
        
        逻辑：
         1. 若当前牌是【闪】或【借刀杀人】，直接尝试发动【技能】。
         2. 若当前牌为【闪电】、【桃】、【酒】且已经使用过1次（即第二次使用），则尝试发动【技能】。
         3. 若当前牌为【杀】且已经使用过2次（第三次使用）且玩家未装备【诸葛连弩】，也尝试发动【技能】。
         4. 否则，正常使用该牌：
              - 检查使用次数是否未超上限，若合法则将对应次数加1；
              - 若与上一张牌花色或点数相同则加1分；
              - 更新上一张牌；
              - 若为武器牌，则让玩家装备。
         5. 返回最终分数。
        """
        # ① 对于不能正常使用的牌或超出使用次数的情况，尝试发动技能
        if card.name in ["闪", "借刀杀人"]:
            result = self.activate_skill(card, player)
            return result
        
        if card.name in ["闪电", "桃", "酒"]:
            if self.usage_counts.get(card.name, 0) >= 1:
                result = self.activate_skill(card, player)
                return result

        if card.name == "杀":
            # 若第三次使用且玩家未装备诸葛连弩则触发技能
            if self.usage_counts.get("杀", 0) >= 2 and not (player.weapon is not None and player.weapon.name == "诸葛连弩"):
                result = self.activate_skill(card, player)
                return result

        # ② 正常结算：先检查使用额度
        max_usage = self.get_max_usage(card.name, player)
        if self.usage_counts.get(card.name, 0) >= max_usage:
            return ILLEGAL
        if card.name in self.usage_counts:
            self.usage_counts[card.name] += 1 
        # ③ 计算得分：若当前牌与上一张牌在花色或点数上有相同，加1分
        score = 0
        if self.last_card is not None:
            if card.suit == self.last_card.suit or card.rank == self.last_card.rank:
                score += 1

        # ④ 更新上一张牌
        self.last_card = card

        # ⑤ 如果当前牌是装备牌，则让玩家装备之
        if card.category == "装备牌":
            player.equip_weapon(card)

        return score
    
    def activate_skill(self, card, player):
        """
        发动【技能】的逻辑：
        0. 若【技能】已发动过或者不存在【上一张牌】，则直接返回非法。
        1. 按顺序尝试将当前牌当作【桃】、【酒】、【杀】来使用，每次尝试时：
            - 无需单独判断【桃】、【酒】、【杀】的额度，settle 自会判断是否达到上限；
            - 消耗【技能】的使用额度；
            - 构造一张新卡牌，其花色、点数与【上一张牌】相同，但牌名变为【桃】/【酒】/【杀】，类别置为“基本牌”；
            - 调用 settle 方法进行结算（包括匹配上一张牌的逻辑）；
            - 若结算成功则打印发动技能情况并返回【技能】得分，否则回滚消耗，尝试下一个选项。
        2. 若所有选项均失败，则返回非法。
        """
        # 条件0：技能已发动过或者不存在上一张牌，直接失败
        if self.usage_counts["技能"] >= self.get_max_usage("技能", player) or self.last_card is None:
            return ILLEGAL

        # 依次尝试【桃】、【酒】、【杀】
        for option in ["桃", "酒", "杀"]:
            # 消耗【技能】的使用额度
            self.usage_counts["技能"] += 1

            # 构造包装牌：花色与上一张牌相同，点数不变，但牌名变为 option，类别固定为“基本牌”
            new_card = Card(
                card_id=card.card_id, 
                name=option, 
                suit=self.last_card.suit, 
                rank=card.rank, 
                category="基本牌"
            )
            # 利用 settle 方法复用原有结算逻辑
            result = self.settle(new_card, player)
            if result != ILLEGAL:
                # 打印发动技能情况：将原牌构造成了虚拟牌
                # print(f"发动技能：将原牌 {card} 构造成虚拟牌 {new_card}，得分：{result}")
                return result

            # 若结算失败，则回滚消耗的【技能】使用额度
            self.usage_counts["技能"] -= 1

        # 若所有尝试均失败，则返回非法
        return ILLEGAL

